#include <gtest/gtest.h>
#include "viml/compiler.h"
#include "viml/vm.h"

namespace viml {

class CompilerTest : public ::testing::Test {
protected:
    Compiler compiler;
    VM vm;
    
    Value execute_source(const std::string& source) {
        auto bytecode = compiler.compile(source, "<test>");
        return vm.execute(bytecode);
    }
    
    void SetUp() override {}
    void TearDown() override {}
};

TEST_F(CompilerTest, CompileSimpleNumber) {
    std::string source = "echo 42";
    Compiler compiler;
    
    auto bytecode = compiler.compile(source);
    
    ASSERT_TRUE(bytecode != nullptr);
    EXPECT_FALSE(bytecode->get_constants().empty());
    EXPECT_FALSE(bytecode->get_instructions().empty());
}

TEST_F(CompilerTest, CompileSimpleString) {
    std::string source = "echo \"Hello, World!\"";
    Compiler compiler;
    
    auto bytecode = compiler.compile(source);
    
    ASSERT_TRUE(bytecode != nullptr);
    EXPECT_FALSE(bytecode->get_constants().empty());
    
    // 检查常量池中有字符串
    const auto& constants = bytecode->get_constants();
    bool found_string = false;
    for (const auto& constant : constants) {
        if (constant.is_string()) {
            found_string = true;
            break;
        }
    }
    EXPECT_TRUE(found_string);
}

TEST_F(CompilerTest, CompileLetStatement) {
    std::string source = "let x = 42";
    Compiler compiler;
    
    auto bytecode = compiler.compile(source);
    
    ASSERT_TRUE(bytecode != nullptr);
    const auto& instructions = bytecode->get_instructions();
    
    // 应该有LOAD_CONST, MOVE, HALT指令
    EXPECT_GE(instructions.size(), 2);
}

TEST_F(CompilerTest, CompileBinaryExpression) {
    std::string source = "echo 1 + 2";
    Compiler compiler;
    
    auto bytecode = compiler.compile(source);
    
    ASSERT_TRUE(bytecode != nullptr);
    const auto& instructions = bytecode->get_instructions();
    
    // 应该有LOAD_CONST, LOAD_CONST, ADD, ECHO, HALT指令
    EXPECT_GE(instructions.size(), 4);
}

TEST_F(CompilerTest, ExecuteCompiledCode) {
    std::string source = "echo 42";
    Compiler compiler;
    VM vm;
    
    auto bytecode = compiler.compile(source);
    ASSERT_TRUE(bytecode != nullptr);
    
    // 执行应该不抛出异常
    EXPECT_NO_THROW(vm.execute(bytecode));
}

TEST_F(CompilerTest, ExecuteLetAndEcho) {
    std::string source = "let x = 42\necho x";
    Value result = execute_source(source);
    EXPECT_EQ(result.type(), ValueType::NIL);  // echo returns nil
}

// 添加while循环测试
TEST_F(CompilerTest, ExecuteWhileLoop) {
    std::string source = R"(
        let i = 0
        while i < 3
            echo i
            let i = i + 1
        endwhile
    )";
    Value result = execute_source(source);
    EXPECT_EQ(result.type(), ValueType::NIL);  // echo returns nil
}

TEST_F(CompilerTest, ExecuteArithmetic) {
    std::string source = "echo 5 + 3 * 2";
    Compiler compiler;
    VM vm;
    
    auto bytecode = compiler.compile(source);
    ASSERT_TRUE(bytecode != nullptr);
    
    // 执行应该不抛出异常
    EXPECT_NO_THROW(vm.execute(bytecode));
}

} // namespace viml